using AutoMapper;
using AutoMapper.Internal;
using HotelManageSystem.Data;
using HotelManageSystem.Dto;
using HotelManageSystem.Model;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace HotelManageSystem.Service {
    public class HotelManageService : IHotelManageService {
        private readonly IMapper _mapper;
        private readonly DataContext _context;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public HotelManageService(IMapper mapper, DataContext context, IHttpContextAccessor httpContextAccessor) {
            this._mapper = mapper;
            this._context = context;
            this._httpContextAccessor = httpContextAccessor;
        }
        private int GetUserId() {
            return int.Parse(_httpContextAccessor.HttpContext!.User.FindFirstValue(ClaimTypes.NameIdentifier)!);
        }

        public async Task<ServiceResponse<int>> 登记预定(AddPreOrderDto newPreOrder) {
            var response = new ServiceResponse<int>();

            // 若身份证号不是18位直接返回
            if (newPreOrder.UserId.Count() != 18) {
                response.Data = -10;
                response.Success = false;
                response.Message = "身份证位数不对.";
                return response;
            }

            var user = await _context.Users.FirstOrDefaultAsync(c => c.Id == newPreOrder.UserId);
            var worker = await _context.Workers.FirstOrDefaultAsync(c => c.Id == GetUserId());
            var room = await _context.Rooms.FirstOrDefaultAsync(c => c.Id == newPreOrder.RoomId);

            // 检查是否已存在用户
            // 若不存在则添加此人信息
            if (user is null) {
                user = new User {
                    Id = newPreOrder.UserId,
                    Name = newPreOrder.UserName,
                    Gender = newPreOrder.Gender,
                    ContactType = newPreOrder.ContactType,
                    ContactData = newPreOrder.ContactData,
                };
                _context.Users.Add(user);
                await _context.SaveChangesAsync();
            }
            else if (worker is null) {
                response.Data = -2;
                response.Success = false;
                response.Message += $"员工:{GetUserId()}不存在.";
                return response;
            }
            else if (room is null) {
                response.Data = -3;
                response.Success = false;
                response.Message += $"房间:{newPreOrder.RoomId}不存在.";
                return response;
            }
            // 若已存在，则检查一下信息对不对得上
            // 若对不上则返回错误信息
            else if (user.Name != newPreOrder.UserName || user.Gender != newPreOrder.Gender) {
                response.Data = -4;
                response.Success = false;
                response.Message += "信息有误.";
            }
            else if (user.ContactType != newPreOrder.ContactType || user.ContactData != newPreOrder.ContactData) {
                response.Message += "联系方式不一致，已更新.";
            }

            // 如果用户已有预定
            if (await _context.PreOrder_UserWorkerRooms.AnyAsync(c => c.UserId == newPreOrder.UserId)) {
                response.Data = -4;
                response.Success = false;
                response.Message += $"用户:\"{newPreOrder.UserId}\"已有预定";
                return response;
            }

            // 然后预定
            var preOrder = _mapper.Map<PreOrder_UserWorkerRoom>(newPreOrder);
            preOrder.User = user;
            preOrder.Worker = worker;
            preOrder.Room = room;
            _context.PreOrder_UserWorkerRooms.Add(preOrder);
            await _context.SaveChangesAsync();

            response.Message += "预订成功.";
            return response;
        }
        public async Task<ServiceResponse<int>> 撤销预定(CancelPreOrderDto canceledPreOrder) {
            var response = new ServiceResponse<int>();

            var user = await _context.Users.FirstOrDefaultAsync(c => c.Id == canceledPreOrder.UserId);
            var room = await _context.Rooms.FirstOrDefaultAsync(c => c.Id == canceledPreOrder.RoomId);

            var preOrder_UserWorkerRooms = await _context.PreOrder_UserWorkerRooms.FirstOrDefaultAsync(c => c.UserId == canceledPreOrder.UserId && c.RoomId == canceledPreOrder.RoomId);

            if (user is null) {
                response.Data = -1;
                response.Success = false;
                response.Message += "用户不存在.";
            }
            else if (room is null) {
                response.Data = -3;
                response.Success = false;
                response.Message += "该房间不存在.";
            }
            else if (preOrder_UserWorkerRooms is null) {
                response.Data = -4;
                response.Success = false;
                response.Message += "没有找到对应的记录.";
            }

            if (!response.Success) {
                return response;
            }

            _context.PreOrder_UserWorkerRooms.Remove(preOrder_UserWorkerRooms!);
            await _context.SaveChangesAsync();
            response.Message += "成功取消预定.";

            return response;
        }
        public async Task<ServiceResponse<int>> 登记用户(AddUserDto newUser) {
            var response = new ServiceResponse<int>();

            // 若身份证号不是18位直接返回
            if (newUser.Id.Count() != 18) {
                response.Data = -10;
                response.Success = false;
                response.Message = "身份证位数不对.";
                return response;
            }

            var user = await _context.Users.FirstOrDefaultAsync(c => c.Id == newUser.Id);

            if (user is not null) {
                response.Data = -1;
                response.Success = false;
                response.Message = "用户已存在.";
                return response;
            }
            else {
                var _newUser = _mapper.Map<User>(newUser);
                _context.Users.Add(_newUser);
                await _context.SaveChangesAsync();

                response.Message = "添加用户成功.";
                return response;
            }
        }
        //查询 -------------------------------\
        public async Task<ServiceResponse<List<获取预定信息Dto>>> 按用户Id查询预定信息(string userId) {
            var response = new ServiceResponse<List<获取预定信息Dto>>();

            var preOrder_UserWorkerRooms = await _context.PreOrder_UserWorkerRooms
                .Include(c => c.User)
                .Include(c => c.Worker)
                .Include(c => c.Room)
                .Where(c => c.UserId == userId)
                .ToListAsync();

            if (preOrder_UserWorkerRooms.Count == 0) {
                response.Success = false;
                response.Message = "查询不到用户:\"{userId}\"的预定信息.";
                return response;
            }

            response.Data = preOrder_UserWorkerRooms.Select(c => {
                return new 获取预定信息Dto {
                    Id = c.Id,
                    UserId = c.UserId,
                    UserName = c.User.Name,
                    WorkerId = c.WorkerId,
                    WorkerName = c.Worker.Name,
                    RoomId = c.RoomId,
                    Model = c.Room.Model,
                    InTime = c.InTime,
                    OutTime = c.OutTime,
                };
            }).ToList();
            response.Message = "成功获取.";
            return response;
        }
        public async Task<ServiceResponse<GetUserDto>> 按用户Id查询用户信息(string userId) {
            var response = new ServiceResponse<GetUserDto>();

            // 若身份证号不是18位直接返回
            if (userId.Count() != 18) {
                response.Success = false;
                response.Message = "身份证位数不对.";
                return response;
            }

            var user = await _context.Users.FirstOrDefaultAsync(c => c.Id == userId);

            if (user is null) {
                response.Success = false;
                response.Message = $"没有找到用户:{userId}.";
                return response;
            }

            response.Data = _mapper.Map<GetUserDto>(user);
            response.Message = "用户信息获取成功.";
            return response;

        }
        public async Task<ServiceResponse<List<GetUserDto>>> 按用户名称查询用户信息(string userName) {
            var response = new ServiceResponse<List<GetUserDto>>();

            var users = await _context.Users.Where(c => c.Name == userName).ToListAsync();

            if (users is null) {
                response.Success = false;
                response.Message = $"没有找到用户:{userName}.";
                return response;
            }

            response.Data = users.Select(c => _mapper.Map<GetUserDto>(c)).ToList();
            response.Message = "用户信息获取成功.";
            return response;
        }
        public async Task<ServiceResponse<List<SearchCheckInInfoDto>>> 按用户Id搜索入住信息(string userId) {
            var response = new ServiceResponse<List<SearchCheckInInfoDto>>();


            var user = await _context.Users.FirstOrDefaultAsync(c => c.Id == userId);
            if (user is null) {
                response.Success = false;
                response.Message = $"用户{userId}不存在.";
                return response;
            }


            var checkIns = await _context.CheckIn_UserWorkerRooms.Include(c => c.Worker).Include(c => c.Room).Where(c => c.User == user).ToListAsync();
            if (checkIns.Count == 0) {
                response.Success = false;
                response.Message = $"用户:{user.Name}没有入住.";
                return response;
            }

            response.Data = checkIns.Select(c => {
                var t = new SearchCheckInInfoDto {
                    UserId = c.UserId,
                    UserName = c.User.Name,
                    WorkerId = c.WorkerId,
                    WorkerName = c.Worker.Name,
                    RoomId = c.RoomId,
                    Model = c.Room.Model,
                    InTime = c.InTime,
                    OutTime = c.OutTime
                };
                return t;
            }).ToList();
            response.Message = "查询完成";
            return response;
        }
        public async Task<ServiceResponse<GetRoomDto>> 按房间号查询房间信息(int roomId) {
            var response = new ServiceResponse<GetRoomDto>();

            var room = await _context.Rooms.FirstOrDefaultAsync(c => c.Id == roomId);

            if (room is null) {
                response.Success = false;
                response.Message = $"房间:{roomId}不存在";
                return response;
            }

            response.Data = _mapper.Map<GetRoomDto>(room);
            response.Message = "用户信息获取成功.";
            return response;
        }
        public async Task<ServiceResponse<List<Bill>>> 查询房间账单(int roomId) {
            var response = new ServiceResponse<List<Bill>>();

            var bills = await _context.Bills.Where(c => c.Room.Id == roomId).ToListAsync();
            if (bills.Count == 0) {
                response.Success = false;
                response.Message = $"房间{roomId}不存在未结账单";
                return response;
            }

            response.Data = bills;
            response.Message = "查询成功.";
            return response;
        }
        public async Task<ServiceResponse<GetWorkerDto>> 通过Id查询员工信息(int workerId) {
            var response = new ServiceResponse<GetWorkerDto>();

            var worker = await _context.Workers.FirstOrDefaultAsync(c => c.Id == workerId);
            if (worker is null) {
                response.Success = false;
                response.Message = $"员工\"{workerId}\"不存在.";
                return response;
            }

            response.Data = _mapper.Map<GetWorkerDto>(worker);
            response.Message = "查询成功.";
            return response;
        }
        public async Task<ServiceResponse<GetWorkerDto>> 通过名称查询员工信息(string workerName) {
            var response = new ServiceResponse<GetWorkerDto>();

            var worker = await _context.Workers.FirstOrDefaultAsync(c => c.Name == workerName);
            if (worker is null) {
                response.Success = false;
                response.Message = $"员工\"{workerName}\"不存在.";
                return response;
            }

            response.Data = _mapper.Map<GetWorkerDto>(worker);
            response.Message = "查询成功.";
            return response;
        }
        public async Task<ServiceResponse<List<GetUserDto>>> 查询所有用户信息() {
            var response = new ServiceResponse<List<GetUserDto>>();

            var users = await _context.Users.ToListAsync();

            response.Data = users.Select(c => _mapper.Map<GetUserDto>(c)).ToList();
            response.Message = "查询成功.";

            return response;

        }
        public async Task<ServiceResponse<List<GetWorkerDto>>> 查询所有员工信息() {
            var response = new ServiceResponse<List<GetWorkerDto>>();

            var workers = await _context.Workers.ToListAsync();

            response.Data = workers.Select(c => _mapper.Map<GetWorkerDto>(c)).ToList();
            response.Message = "查询成功.";

            return response;

        }
        public async Task<ServiceResponse<List<GetRoomDto>>> 查询所有房间信息() {
            var response = new ServiceResponse<List<GetRoomDto>>();

            var rooms = await _context.Rooms.ToListAsync();

            response.Data = rooms.Select(c => _mapper.Map<GetRoomDto>(c)).ToList();
            response.Message = "查询成功.";

            return response;

        }
        public async Task<ServiceResponse<Dictionary<int, List<TimePair>>>> 查询预定以及入住时间(){
            var response = new ServiceResponse<Dictionary<int, List<TimePair>>>();
            // 字典，键是房间，值则是房间对应的房间被占用的时间对列表
            var roomThatOccupiedTimes = new Dictionary<int,List<TimePair>>();
            // 对每个房间创建键值对，以准备接下来的操作
            await _context.Rooms.ForEachAsync
                (c => roomThatOccupiedTimes.Add(c.Id,new List<TimePair>()));
            // 遍历入住和预定表，找出所有房间被占用的时间段
            await _context.PreOrder_UserWorkerRooms.ForEachAsync
                (c => {
                    roomThatOccupiedTimes.TryGetValue(c.RoomId, out List<TimePair> timePairs);
                    timePairs.Add(new TimePair { InTime = c.InTime, OutTime = c.OutTime });
                });
            await _context.CheckIn_UserWorkerRooms.ForEachAsync
                (c => {
                    roomThatOccupiedTimes.TryGetValue(c.RoomId, out List<TimePair> timePairs);
                    timePairs.Add(new TimePair { InTime = c.InTime, OutTime = c.OutTime });
                });
            // 返回结果
            response.Data = roomThatOccupiedTimes;
            response.Message = "查询成功.";
            return response;

        }
        //查询 -------------------------------/
        public async Task<ServiceResponse<int>> 房间变更(房间变更Dto dto) {
            var response = new ServiceResponse<int>();
            // 检查用户是否已有入住
            var checkIn = await _context.CheckIn_UserWorkerRooms
                .Include(c => c.User)
                .Include(c => c.Worker)
                .Include(c => c.Room)
                .FirstOrDefaultAsync(c => c.UserId == dto.UserId);
            if (checkIn is null) {
                response.Success = false;
                response.Message = $"用户:{dto.UserId} 没有入住";
                return response;
            }
            // 检查目标房间是否存在
            var targetRoom = await _context.Rooms.FirstOrDefaultAsync(c => c.Id == dto.targetRoomId);
            if (targetRoom is null) {
                response.Success = false;
                response.Message = $"房间{dto.targetRoomId}不存在";
                return response;
            }
            //

            // 创建新的入住信息，并修改信息
            var newCheckIn = new CheckIn_UserWorkerRoom {
                UserId = checkIn.UserId,
                WorkerId = checkIn.WorkerId,
                RoomId = checkIn.RoomId,
                InTime = checkIn.InTime,
                OutTime = checkIn.OutTime,

                User = checkIn.User,
                Worker = checkIn.Worker,
                Room = targetRoom,
            };
            targetRoom.State = EnumRoomState.占用;
            checkIn.Room.State = EnumRoomState.空闲;
            // 删除旧的
            _context.CheckIn_UserWorkerRooms.Remove(checkIn);
            _context.CheckIn_UserWorkerRooms.Add(newCheckIn);
            // 返回
            await _context.SaveChangesAsync();

            return response;
        }
        public async Task<ServiceResponse<int>> 房间状态变更(房间状态变更Dto dto) {
            var response = new ServiceResponse<int>();

            var room = await _context.Rooms.FirstOrDefaultAsync(c => c.Id == dto.RoomId);
            if (room is null) {
                response.Success = false;
                response.Message = $"房间{dto.RoomId}不存在";
                return response;
            }


            if (room.State != EnumRoomState.占用) {
                room.State = dto.State;
                await _context.SaveChangesAsync();
            }

            response.Message = "变更成功.";
            return response;
        }
        public async Task<ServiceResponse<int>> 房型价格变更(更改房间价格Dto dto) {
            var response = new ServiceResponse<int>();

            var rooms = await _context.Rooms.Where(c => c.Model == dto.RoomModel).ToListAsync();
            if (rooms.Count == 0) {
                response.Success = false;
                response.Message = $"不存在该房型:\"{dto.RoomModel}\"的房间.";
                return response;
            }

            rooms.ForEach(c => c.Price = dto.Price);
            await _context.SaveChangesAsync();

            response.Message = "房间价格更改成功.";
            return response;
        }
        public async Task<ServiceResponse<int>> 通过预定入住(int preOrderId) {
            var response = new ServiceResponse<int>();

            var preOrder = await _context.PreOrder_UserWorkerRooms
                .Include(c => c.User)
                .Include(c => c.Worker)
                .Include(c => c.Room)
                .FirstOrDefaultAsync(c => c.Id == preOrderId);
            if (preOrder is null) {
                response.Data = -1;
                response.Success = false;
                response.Message += $"预定:\"{preOrderId}\"不存在.";
                return response;
            }


            var user = preOrder.User;
            var worker = await _context.Workers.FirstOrDefaultAsync(c => c.Id == GetUserId());
            if (worker is null) {
                response.Data = -2;
                response.Success = false;
                response.Message += $"员工:{GetUserId()}不存在.";
                return response;
            }
            var room = preOrder.Room;

            room.State = EnumRoomState.占用;
            var _newCheckInInfo = new CheckIn_UserWorkerRoom {
                UserId = user.Id,
                WorkerId = worker.Id,
                RoomId = room.Id,
                InTime = preOrder.InTime,
                OutTime = preOrder.OutTime,

                User = user,
                Worker = worker,
                Room = room,
            };

            _context.PreOrder_UserWorkerRooms.Remove(preOrder);
            _context.CheckIn_UserWorkerRooms.Add(_newCheckInInfo);
            await _context.SaveChangesAsync();

            response.Message = "入住登记成功。";
            return response;

        }
        public async Task<ServiceResponse<int>> 直接入住(入住Dto dto) {
            var response = new ServiceResponse<int>();

            var user = await _context.Users.FirstOrDefaultAsync(c => c.Id == dto.UserId);
            if (user is null) {
                await 登记用户(new AddUserDto() {
                    Id = dto.UserId,
                    Name = dto.UserName,
                    Gender = dto.Gender,
                    ContactType = dto.ContactType,
                    ContactData = dto.ContactData
                });
                user = await _context.Users.FirstOrDefaultAsync(c => c.Id == dto.UserId);
            }

            var worker = await _context.Workers.FirstOrDefaultAsync(c => c.Id == GetUserId());

            var room = await _context.Rooms.FirstOrDefaultAsync(c => c.Id == dto.RoomId);
            if (room is null) {
                response.Success = false;
                response.Message = $"房间\"{dto.RoomId}\"不存在.";
                return response;
            }
            else if (room.State != EnumRoomState.空闲) {
                response.Success = false;
                response.Message = $"房间\"{dto.RoomId}\"已占用.";
                return response;
            }
            room.State = EnumRoomState.占用;


            var _newCheckInInfo = new CheckIn_UserWorkerRoom {
                UserId = user.Id,
                WorkerId = worker.Id,
                RoomId = dto.RoomId,
                InTime = dto.InTime,
                OutTime = dto.OutTime,

                User = user,
                Worker = worker,
                Room = room,
            };

            _context.CheckIn_UserWorkerRooms.Add(_newCheckInInfo);
            await _context.SaveChangesAsync();

            response.Message = "入住登记成功。";
            return response;
        }
        public async Task<ServiceResponse<int>> 添加房间(AddRoomDto newRoom) {
            var response = new ServiceResponse<int>();

            var room = await _context.Rooms.FirstOrDefaultAsync(c => c.Id == newRoom.Id);
            if (room is not null) {
                response.Success = false;
                response.Message = $"房间:\"{newRoom.Id}\"已存在.";
                return response;
            }

            var _room = new Room();
            _room.Id = newRoom.Id;
            _room.State = EnumRoomState.空闲;
            _room.Model = newRoom.Model;
            var rType = await _context.RTypes.FirstOrDefaultAsync(c => c.Id == _room.Model);
            _room.Price = rType.Price;

            _context.Rooms.Add(room);
            await _context.SaveChangesAsync();

            response.Message = $"房间{newRoom.Id}添加成功.";
            return response;
        }
        public async Task<ServiceResponse<int>> 添加账单(添加账单Dto dto) {
            var response = new ServiceResponse<int>();

            var worker = await _context.Workers.FirstOrDefaultAsync(c => c.Id == GetUserId());
            var room = await _context.Rooms.FirstOrDefaultAsync(c => c.Id == dto.RoomId);

            var checkIn = await _context.CheckIn_UserWorkerRooms.FirstOrDefaultAsync(c => c.RoomId == dto.RoomId);
            if(checkIn is null) {
                response.Success = false;
                response.Message = $"此房间\"{dto.RoomId}\"没有人住.";
                return response;
            }

            for (int i = 0; i < dto.Quantity; i++) {
                _context.Bills.Add(new Bill {
                    Item = dto.Item,
                    Price = dto.Price,
                    Time = dto.Time,
                    Room = room,
                    Worker = worker,
                });
            }

            await _context.SaveChangesAsync();

            response.Message = "添加成功.";
            return response;
        }
        public async Task<ServiceResponse<获取账单信息Dto>> 按房间Id查询账单信息随后结账(int roomId) {
            var response = new ServiceResponse<获取账单信息Dto>();
            var retBills = new 获取账单信息Dto();

            var checkIn = await _context.CheckIn_UserWorkerRooms
                .Include(c => c.User)
                .Include(c => c.Room)
                .Include(c => c.Room.Bills)
                .FirstOrDefaultAsync(c => c.RoomId == roomId);
            if (checkIn is null) {
                response.Success = false;
                response.Message = $"入住记录: Room_{roomId}不存在";
                return response;
            }
            // 房间的账单，只用于计算总价，暂不存入数据库
            var timePair = new TimePair {
                InTime = checkIn.InTime,
                OutTime = DateTime.Now
            };
            var billOfRoom = new Bill {
                //Id = // Id由数据库自动生成
                Item = $"退房:房型\"{checkIn.Room.Model}\"房号\"{checkIn.Room.Id}\"天数\"{timePair.GetDays()}\"",
                Price = checkIn.Room.Price * timePair.GetDays(),
                Room = checkIn.Room,
                Worker = await _context.Workers.FirstOrDefaultAsync(c => c.Id == GetUserId()),
            };
            retBills.RoomId = checkIn.Room.Id;
            retBills.Bills.AddRange(checkIn.Room.Bills.Select(c => _mapper.Map<单账单Dto>(c)).ToList());
            retBills.Bills.Add(_mapper.Map<单账单Dto>(billOfRoom));
            retBills.Bills.ForEach(c => retBills.Sum += c.Price);

            response.Data = retBills;
            response.Message = "查询账单成功.";
            return response;
        }
        public async Task<ServiceResponse<int>> 结账(int roomId) {
            var response = new ServiceResponse<int>();

            var checkIn = await _context.CheckIn_UserWorkerRooms
                .Include(c => c.User)
                .Include(c => c.Room)
                .Include(c => c.Room.Bills)
                .FirstOrDefaultAsync(c => c.RoomId == roomId);
            if (checkIn is null) {
                response.Success = false;
                response.Message = $"入住记录: Room_{roomId}不存在";
                return response;
            }

            //// 房间的账单
            //var timePair = new TimePair {
            //    InTime = checkIn.InTime,
            //    OutTime = checkIn.OutTime
            //};
            //var billOfRoom = new Bill {
            //    //Id = // Id由数据库自动生成
            //    Item = $"退房:房型\"{checkIn.Room.Model}\"房号\"{checkIn.Room.Id}\"天数\"{timePair.GetDays()}\"",
            //    Price = checkIn.Room.Price * timePair.GetDays(),
            //    Room = checkIn.Room,
            //    Worker = await _context.Workers.FirstOrDefaultAsync(c => c.Id == GetUserId()),
            //};

            checkIn.Room.State = EnumRoomState.空闲;
            _context.Bills.RemoveRange(checkIn.Room.Bills);
            _context.CheckIn_UserWorkerRooms.Remove(checkIn);
            await _context.SaveChangesAsync();

            return response;
        }









        public async Task<ServiceResponse<int>> AddWorker(AddWorkerDto newWorker) {
            throw new NotImplementedException();
        }



        public Task<ServiceResponse<GetWorkerDto>> GetWorker(string workerId) {
            throw new NotImplementedException();
        }

        public Task<ServiceResponse<GetRoomDto>> UpdateRoom(UpdateRoomDto updatedRoom) {
            throw new NotImplementedException();
        }
    }
}